<template>
  <div class="_ehl_edit_div" contenteditable="true" :ref="ref"> </div>
</template>

<script>
  import Vue from 'vue'
  import { Upload } from 'element-ui'
  Vue.use(Upload)
  export default {
    name: '',
    props: {
      value: { type: Array, default: () => [] },
      //value的key映射
      prop: { type: Object, default: () => ({ label: 'label', id: 'id' }) },
      //生成的图片的内边距
      padding: { type: Number, default: () => 20 },
      //生成的图片的高度
      height: { type: Number, default: () => 34 },
      //图片背景填充颜色
      fillColor: { type: String, default: () => '#f2f4f8' },
      //文字大小
      fontSize: { type: Number, default: () => 14 },
      //文字颜色
      fontColor: { type: String, default: () => '#3b424c' },
    },
    data() {
      return {
        ref: `edit_div_ref_${Math.random()}`,
        label_p: this.prop['label'],
        value_p: this.prop['id'],
      }
    },
    mounted() {
      this.value.forEach(item => {
        this.addElement(item)
      })
      this.$refs[this.ref].oninput = () => {
        this.$emit('input', this.getNodeValue())
      }
    },
    methods: {
      addElement(obj) {
        const imgTag = document.createElement('img')
        let tmp = this.drawLogo(obj[this.label_p])
        imgTag.src = tmp.url
        imgTag.style.height = tmp.height
        imgTag.style.width = tmp.width
        imgTag.style.borderRadius = '5px'
        imgTag.style.margin = '0px 10px 0 0'
        imgTag.setAttribute('id', `${obj[this.value_p]}`)
        imgTag.setAttribute('data-value', JSON.stringify(obj))

        let exitNode = this.getSameNodes(obj)
        if (!isEmpty(exitNode) && obj[this.value_p]) {
          let childId = obj[this.value_p]
          let box = document.getElementById(childId)
          this.$refs[this.ref].insertBefore(imgTag, box) //向box的前一个位置添加img
          box.parentNode.removeChild(box)
        } else {
          this.insertHtmlAtCaret(imgTag)
        }
        this.$emit('input', this.getNodeValue())
      },
      //清空所有项
      delAll() {
        this.$refs[this.ref].innerHTML = ''
        this.$emit('input', [])
      },
      //删除某一项
      delItem(id) {
        let box = document.getElementById(id)
        if (box) {
          box.parentNode.removeChild(box)
          this.$emit('input', this.getNodeValue())
        }
      },
      //查找已添加的节点中是否有和要添加的节点相同的项
      getSameNodes(obj) {
        let childNode = this.getNodeValue()
        let exitNode = childNode.find(item => {
          return item[this.value_p] === obj[this.value_p]
        })
        return exitNode
      },
      insertHtmlAtCaret(html) {
        let sel = window.getSelection()
        if (sel) {
          if (
            sel.focusNode &&
            sel.focusNode.className &&
            sel.focusNode.className.includes('_ehl_edit_div')
          ) {
            //获得焦点--光标处插入节点再将光标移到最后
            let range = sel.getRangeAt(0)
            range.insertNode(html)
            sel.selectAllChildren(this.$refs[this.ref]) //range 选择obj下所有子内容
            sel.collapseToEnd() //光标移至最后
          } else {
            //没有获得焦点--直接在div最后添加节点
            sel.selectAllChildren(this.$refs[this.ref]) //range 选择obj下所有子内容
            sel.collapseToEnd() //光标移至最后
            let range = sel.getRangeAt(0)
            range.insertNode(html)
          }
          sel.removeAllRanges() //清除选中状态
        }
      },
      getNodeValue() {
        let tmp = []
        let childNodes = this.$refs[this.ref].childNodes //获取逻辑配置已添加的所有项
        for (let i = 0; i < childNodes.length; i++) {
          if (childNodes[i].dataset) {
            tmp.push(JSON.parse(childNodes[i].dataset.value))
          }
        }
        return tmp
      },
      //根据文字生成图片
      drawLogo(text) {
        let canvas = document.createElement('canvas')
        let context = canvas.getContext('2d')
        context.font = '20px sans-serif'
        let width = context.measureText(text).width
        canvas.width = width + this.padding
        canvas.height = this.height
        context.fillStyle = this.fillColor
        //先填充背景
        context.fillRect(0, 0, canvas.width, canvas.height)
        context.textAlign = 'center'
        context.textBaseline = 'middle'
        context.fillStyle = this.fontColor
        context.font = `${this.fontSize}px sans-serif`
        //再填充文字
        context.fillText(text, canvas.width / 2, canvas.height / 2)
        let dataUrl = canvas.toDataURL('image/png')
        return { url: dataUrl, width: canvas.width + 'px', height: this.height + 'px' }
      },
    },
  }
</script>
